package wiz.client.ui;

import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;

public class TransitionPanel extends SimplePanel {

	private static final TransitionStrategy SLIDE_TRANSITION = new TransitionStrategy() {
		
		@Override
		public String[] getOutgoingTransitionStyles() {
			return new String[0];
		}
		
		@Override
		public int getOutgoingTransitionDelay() {
			return 0;
		}
		
		@Override
		public String[] getOutgoingPreTransitionStyles() {
			return new String[0];
		}
		
		@Override
		public String[] getIncomingTransitionStyles() {
			return new String[] {
					"transitionFinalPosition"
			};
		}
		
		@Override
		public String[] getIncomingPreTransitionStyles() {
			return new String[] {
					"transitionOriginalPosition",
					"transitionSlideTransition"
			};
		}

		@Override
		public int getIncomingTransitionDelay() {
			return 500;
		}
	};
	
	private static final TransitionStrategy FADE_TRANSITION_STRATEGY = new TransitionStrategy() {
		
		@Override
		public String[] getOutgoingTransitionStyles() {
			return new String[] {
					"transitionFadeTransitionFadeOut"
			};
		}
		
		@Override
		public int getOutgoingTransitionDelay() {
			return 500;
		}
		
		@Override
		public String[] getOutgoingPreTransitionStyles() {
			return new String[] {
					"transitionFadeTransitionFadeIn",
					"transitionFadeTransition"
			};
		}
		
		@Override
		public String[] getIncomingTransitionStyles() {
			return new String[] {
					"transitionFadeTransitionFadeIn"
			};
		}
		
		@Override
		public String[] getIncomingPreTransitionStyles() {
			return new String[] {
					"transitionFadeTransitionFadeOut",
					"transitionFadeTransition"
					
			};
		}

		@Override
		public int getIncomingTransitionDelay() {
			return 500;
		}
	};
	
	private static final TransitionStrategy NULL_TRANSITION_STRATEGY = new TransitionStrategy() {
		
		@Override
		public String[] getOutgoingTransitionStyles() {
			return new String[0];
		}
		
		@Override
		public int getOutgoingTransitionDelay() {
			return 0;
		}
		
		@Override
		public String[] getOutgoingPreTransitionStyles() {
			return new String[0];
		}
		
		@Override
		public String[] getIncomingTransitionStyles() {
			return new String[0];
		}
		
		@Override
		public String[] getIncomingPreTransitionStyles() {
			return new String[0];
		}

		@Override
		public int getIncomingTransitionDelay() {
			return 0;
		}
	};
	
	
	private TransitionStrategy fStrategy;

	public TransitionPanel() {
		super();
		fStrategy = FADE_TRANSITION_STRATEGY;
	}

	@Override
	public void setWidget(final Widget w) {
		if (w == null) {
//			super.setWidget(w);
		} else {
			if(getWidget() != null){
				doOutgoingPreTransition();
				
				final String[] outgoingTransitionStyles = fStrategy.getOutgoingTransitionStyles();
				if(outgoingTransitionStyles.length > 0){
					Scheduler.get().scheduleDeferred(new ScheduledCommand() {
	
						@Override
						public void execute() {
							doOutgoingTransition();
							setIncomingWidget(w);
						}
					});
				}else {
					setIncomingWidget(w);
				}
			} else {
				setIncomingWidget(w);
			}
		}

	}

	private void setIncomingWidget(final Widget w) {
		if(fStrategy.getOutgoingTransitionDelay() > 0){
			Scheduler.get().scheduleFixedPeriod(new RepeatingCommand(){
				@Override
				public boolean execute() {
					TransitionPanel.super.setWidget(w);
					doIncomingTransition();
					return false;
				}
			}, fStrategy.getOutgoingTransitionDelay());
		} else {
			TransitionPanel.super.setWidget(w);
			doIncomingTransition();
		}
		
	}

	private void doIncomingTransition() {
		String[] outgoingPreTransitionStyles = fStrategy.getIncomingPreTransitionStyles();
		for (String string : outgoingPreTransitionStyles) {
			getWidget().setStyleName(string, true);
		}
		
		if(fStrategy.getIncomingTransitionStyles().length > 0){
			Scheduler.get().scheduleDeferred(new ScheduledCommand(){
				@Override
				public void execute() {
					for(String style : fStrategy.getIncomingTransitionStyles()){
						getWidget().setStyleName(style,true);
					}
					
					
					Scheduler.get().scheduleDeferred(new ScheduledCommand(){

						@Override
						public void execute() {
							cleanupIncomingTransitions();							
						}
					});
					
				}
			});
		} else {
			cleanupIncomingTransitions();
		}
	}

	protected void cleanupIncomingTransitions() {
		
		Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
			
			@Override
			public boolean execute() {
				for (String s : fStrategy.getIncomingPreTransitionStyles()) {
					getWidget().setStyleName(s, false);
				}
				
				for (String s : fStrategy.getIncomingTransitionStyles()) {
					getWidget().setStyleName(s, false);
				}				
				
				return false;
			}
		}, fStrategy.getIncomingTransitionDelay());
	}

	private void doOutgoingPreTransition() {
		String[] outgoingPreTransitionStyles = fStrategy.getOutgoingPreTransitionStyles();
		for (String string : outgoingPreTransitionStyles) {
			getWidget().setStyleName(string, true);
		}
	}

	private void doOutgoingTransition() {
		String outgoingTransitionStyles[] = fStrategy.getOutgoingTransitionStyles();
		for (String string : outgoingTransitionStyles) {
			getWidget().setStyleName("string", true);							
		}
	}

}
